package org.budo.mongo.jdbc.driver.statement.impl;

import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;

import org.budo.mongo.jdbc.driver.BudoMongoJdbcPreparedStatement;
import org.budo.mongo.jdbc.driver.resultset.BasicDbListResultSet;
import org.budo.mongo.jdbc.driver.statement.AbstractMongoStatement;
import org.budo.support.slf4j.Slf4j;
import org.slf4j.Logger;

import com.mongodb.BasicDBList;
import com.mongodb.DB;
import com.mongodb.MongoCommandException;

/**
 * @author lmw
 */
public class MongoEvalFindStatement extends AbstractMongoStatement {
    private static final Logger log = Slf4j.getLogger();

    private static final String EVAL_FUNCTION_SCRIPT = "var cursorToArray = function (cursor) {" //
            + "    var result = [];" //
            + "    while (cursor.hasNext()) {" //
            + "        result.push(cursor.next());" //
            + "    }" //
            + "    return result;" //
            + "};" //
            + "" //
            + "var copyToTable = function (cursor, tableTo) {" //
            + "    while (cursor.hasNext()) {" //
            + "        db[tableTo].insert(cursor.next());" //
            + "    }" //
            + "};";

    private String evalScript;

    /**
     * @see org.budo.mongo.jdbc.driver.parser.jsqlparser.JSqlParserMongoStatementParser#mongoEvalFindStatement
     */
    public void execute(PreparedStatement preparedStatement) throws SQLException{
        BudoMongoJdbcPreparedStatement mongoPreparedStatement = (BudoMongoJdbcPreparedStatement) preparedStatement;

        List<Timestamp> timestampTemporary = new ArrayList<Timestamp>();
        String evalScript = this.getEvalScript();

        String evalScriptWithParams = this.statementJsonReplaceParameterValues(evalScript, mongoPreparedStatement.getParameterMap(), timestampTemporary);

        log.debug("evalScriptWithParams={}", evalScriptWithParams);

        DB db = this.getMongoDb(mongoPreparedStatement);
        Object result = this.dbEval(db, EVAL_FUNCTION_SCRIPT + evalScriptWithParams);
        BasicDBList basicDBList = (BasicDBList) result;
        mongoPreparedStatement.resultSet(new BasicDbListResultSet(basicDBList));
    }

    private Object dbEval(DB db, String code) {
        try {
            return db.eval(code);
        } catch (MongoCommandException e) {
            throw new RuntimeException("#66 mongo.eval.code=" + code, e);
        }
    }

    public String getEvalScript() {
        return evalScript;
    }

    public void setEvalScript(String evalScript) {
        this.evalScript = evalScript;
    }
}